package com.lenovo.lcdm.type.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.lenovo.lcdm.common.enums.CommonMsgEnum;
import com.lenovo.lcdm.common.exception.BusinessException;
import com.lenovo.lcdm.common.exception.ServiceException;
import com.lenovo.lcdm.type.dto.TypeDefinitionDTO;
import com.lenovo.lcdm.type.dto.TypeDefinitionTreeDTO;
import com.lenovo.lcdm.type.entity.TypeDefinition;
import com.lenovo.lcdm.type.entity.TypeDefinitionMaster;
import com.lenovo.lcdm.type.entity.TypeGlobalAttribute;
import com.lenovo.lcdm.type.enums.DataTypeEnum;
import com.lenovo.lcdm.type.service.*;
import com.lenovo.lcdm.type.util.ObjectUtil;
import com.lenovo.lcdm.type.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.sql.SQLException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Auther xujing30
 * @Date 2024/01/17
 * @Description
 */
@Service
public class TypeAttributeExtServiceImpl implements TypeAttributeExtService {

    private final Logger logger = LoggerFactory.getLogger(TypeAttributeExtServiceImpl.class);

    private static final String DATA_TIME_TYPE_NAME="DateTime";

    public static final String REFERENCE_TABLE_POSTFIX = "_attribute";

    public static final String DB_COLUMN_CREATE_TIME = "create_time";

    public static final String DB_COLUMN_MODIFY_TIME = "modify_time";

    public static final String REFERENCE_TABLE_ID = "id";

    public static final String MULTIPLE_VALUE_SPLITTER = "&&&&&";

    @Autowired
    private TypeDefinitionService typeDefinitionService;

    @Autowired
    private TypeDefinitionMasterService typeDefinitionMasterService;

    @Autowired
    private TypeGlobalAttributeService globalAttributeService;
    @Autowired
    private TypeLocalAttributeService localAttributeService;

//    @Autowired
//    private TypeLocalAttributeLinkService localAttributeLinkService;

    @Override
    public Map<String, List<AttributeDetailView>> getAttributeValuesWithGroup(Typed typed) {
        if (typed == null) {
            return null;
        }
        Map<String, List<AttributeDetailView>> attributeModelWithGroup = new LinkedHashMap<>();
        List<AttributeDetailView> attributeDetailViewList = getAttributeValues(typed);
        Map<Long, AttributeDetailView> attributeDetailViewMap = attributeDetailViewList.stream().collect(
                Collectors.toMap(attributeDetailView -> (attributeDetailView.getLocalAttributeModel().getGlobalAttributeId()),
                        Function.identity(), (attributeDetailView1, attributeDetailView2) -> attributeDetailView1));
        Map<String, List<LocalAttributeModel>> localAttributeModelMap = getLocalAttributeModelsGroupMap(typed.getTypeId());
        localAttributeModelMap.keySet().forEach(attributeModelWithGroupKey -> {
            attributeModelWithGroup.put(attributeModelWithGroupKey,
                    localAttributeModelMap.get(attributeModelWithGroupKey).stream().map(localAttributeModel -> {
                        AttributeDetailView attributeDetailView = attributeDetailViewMap.get(localAttributeModel.getGlobalAttributeId());
                        return attributeDetailView == null ? new AttributeDetailView(localAttributeModel, null) : attributeDetailView;
                    }).collect(Collectors.toList()));
        });
        return attributeModelWithGroup;
    }

    private Map<String, List<LocalAttributeModel>> getLocalAttributeModelsGroupMap(long typeId) {
        TypeDefinitionModel typeDefinitionModel = this.getTypeDetail(typeId);
        return typeDefinitionModel != null ? typeDefinitionModel.getLocalAttributesWithGroup() : null;
    }

    @Override
    public List<AttributeDetailView> getAttributeValues(Typed typed) {
        if (typed == null) {
            return new ArrayList<>();
        }

        Map<Long, List<AttributeDetailView>> objectValuesMap = _getAttributeValues(Collections.singletonList(typed), null);
        if (!CollectionUtils.isEmpty(objectValuesMap)) {
            return objectValuesMap.values().stream().findFirst().orElse(new ArrayList<>());
        }
        return null;
    }

    protected Map<Long, List<AttributeDetailView>> _getAttributeValues(List<? extends Typed> typedList, List<Long> attributeIds) {
        if(ObjectUtil.isAnyEmpty(typedList)) {
            throw new BusinessException("Input objects could not be null!", CommonMsgEnum.FAIL.getCode());
        }
        //remote duplicate ids
        if (!CollectionUtils.isEmpty(attributeIds)) {
            attributeIds = attributeIds.stream().distinct().collect(Collectors.toList());
        }
        List<LocalAttributeModel> localAttributeModels;
        //if inputted attribute ids are empty then get all attributes
        if (CollectionUtils.isEmpty(attributeIds)) {
            localAttributeModels = getLocalAttributeModels(typedList.get(0).getTypeId());
        } else {
            localAttributeModels = getLocalAttributeModels(typedList.get(0), attributeIds);
        }
        // 根据ids和attribute ids组装信息
        return assembleAttributeDetailViewsByTyped(localAttributeModels, typedList);
    }



    @Override
    public void saveAttributeValues(Typed typed, Map<Long, Object> valuesMap) {
        saveAttributeValues(typed, valuesMap, true);
    }

    @Override
    public void saveAttributeValues(Typed typed, Map<Long, Object> valuesMap, boolean needValidate) {
        if (ObjectUtil.isAnyEmpty(typed, valuesMap)) {
            return;
        }

        //查询类型属性表名
        String tableName = getAttributeTableFromTypeId(typed.getTypeId());
        if(tableName == null){
            throw new BusinessException("Type Reference Table not exist!", CommonMsgEnum.FAIL.getCode());
        }

        //查询属性字段名
        Map<Long, String> globalAttributeInternalIdMap = localAttributeService.getGlobalAttributeInternalIdMap(typed.getTypeId());

        //todo needValidate
        if(needValidate){
            List<TypeGlobalAttribute> globalAttributes = globalAttributeService.listByIds(valuesMap.keySet());

        }

        String insertJoin = "";
        String insertValueJoin = "";
        String updateJoin = "";
        for(Long globalAttributeId: valuesMap.keySet()) {
            if (globalAttributeInternalIdMap.get(globalAttributeId) == null) {
                throw new BusinessException("Type Attribute not exist! globalId= " + globalAttributeId, CommonMsgEnum.FAIL.getCode());
            }
            insertJoin += globalAttributeInternalIdMap.get(globalAttributeId) + ",";
            if(valuesMap.get(globalAttributeId)==null){
                insertValueJoin +=  "null,";
            }else{
                insertValueJoin += "'" + valuesMap.get(globalAttributeId).toString() + "',";
            }
            if(valuesMap.get(globalAttributeId) == null){
                updateJoin += globalAttributeInternalIdMap.get(globalAttributeId) + "= null,";
            }else{
                updateJoin += globalAttributeInternalIdMap.get(globalAttributeId) + "='" + valuesMap.get(globalAttributeId).toString() + "',";
            }

        }

        String querySql = "select count(1) from " + tableName + " where id = " + typed.getId();
        long count = SqlRunner.db().selectCount(querySql);
        String now = DateUtil.now();
        if(count == 0){
            String insertSql = "insert into  " + tableName + "(id," + insertJoin + DB_COLUMN_CREATE_TIME + "," + DB_COLUMN_MODIFY_TIME + ") values(" + typed.getId() + ","+ insertValueJoin + "'"+ now + "','" + now + "')" ;
            SqlRunner.db().insert(insertSql);
        }else if(count == 1){
            String updateSql = "update " + tableName + " set " + updateJoin + DB_COLUMN_MODIFY_TIME + "='" + now + "' where id=" + typed.getId() ;
            SqlRunner.db().update(updateSql);
        }else {
            throw new BusinessException("Query type attribute failed, type=" + typed.getObjectClass(), CommonMsgEnum.FAIL.getCode());
        }
    }


    @Override
    public LocalAttributeModel getLocalAttributeModel(Long typeId, Long globalAttributeId) {
        TypeDefinitionModel typeDefinitionModel = getTypeDetail(typeId);
        if (typeDefinitionModel == null || CollectionUtils.isEmpty(typeDefinitionModel.getLocalAttributes())) {
            return null;
        }
        for (LocalAttributeModel localAttributeModel : typeDefinitionModel.getLocalAttributes()) {
            if (localAttributeModel.getGlobalAttributeId().equals(globalAttributeId)) {
                return localAttributeModel;
            }
        }
        return null;
    }

    @Override
    public LocalAttributeModel getLocalAttribute(Long typeId, String attributeName) {
        TypeDefinitionModel typeDefinitionModel = getTypeDetail(typeId);
        if (typeDefinitionModel == null || CollectionUtils.isEmpty(typeDefinitionModel.getLocalAttributes())) {
            return null;
        }
        for (LocalAttributeModel localAttributeModel : typeDefinitionModel.getLocalAttributes()) {
            if (localAttributeModel.getName().equals(attributeName)) {
                return localAttributeModel;
            }
        }
        return null;
    }


    @Override
    public void deleteAttributeValue(Typed typed, List<Long> values) {
        //查询类型属性表名
        String tableName = getAttributeTableFromTypeId(typed.getTypeId());
        if(tableName == null){
            throw new BusinessException("Type Reference Table not exist!", CommonMsgEnum.FAIL.getCode());
        }
        if(CollectionUtils.isEmpty(values)){
            String deleteSql = "delete from " + tableName + " where id=" + typed.getId();
            SqlRunner.db().delete(deleteSql);
        }else{
            Map<Long, Object> valuesMap = values.stream().collect(Collectors.toMap(Function.identity(), null));
            this.saveAttributeValues(typed, valuesMap);
        }

    }

    @Override
    public void saveAttributeValue(Typed typed, Long globalAttributeId, Object value) {
        if (ObjectUtil.isAnyEmpty(typed, globalAttributeId)) {
            return;
        }
        //查询属性字段名
        String internalId = localAttributeService.queryByGlobalAttributeIdAndType(typed.getTypeId(), globalAttributeId);
        if(StringUtils.isEmpty(internalId)){
            throw new BusinessException("Type Attribute not exist!", CommonMsgEnum.FAIL.getCode());
        }
        //查询类型属性表名
        String tableName = getAttributeTableFromTypeId(typed.getTypeId());
        if(tableName == null){
            throw new BusinessException("Type Reference Table not exist!", CommonMsgEnum.FAIL.getCode());
        }
        String querySql = "select count(1) from " + tableName + " where id = " + typed.getId();
        long count = SqlRunner.db().selectCount(querySql);
        String now = DateUtil.formatDateTime(new Date());
        if(count == 0){
            String insertSql = "insert into  " + tableName + "(id," + internalId + "," + DB_COLUMN_CREATE_TIME + "," + DB_COLUMN_MODIFY_TIME + ") values(" + typed.getId() + ",' "+ value.toString() + "','" + now + "','" + now + "')" ;
            SqlRunner.db().insert(insertSql);
        }else if(count == 1){
            String updateSql = "update " + tableName + " set " + internalId + "='" + value.toString() + "'," + DB_COLUMN_MODIFY_TIME + "='" + now + "' where id=" + typed.getId() ;
            SqlRunner.db().update(updateSql);
        }else {
            throw new BusinessException("Query type attribute failed, type=" + typed.getObjectClass(), CommonMsgEnum.FAIL.getCode());
        }
    }

    @Override
    public String getAttributeTableFromTypeId(Long typeId) {
        TypeDefinition typeDefinition = typeDefinitionService.getById(typeId);
        if(typeDefinition == null){
            return null;
        }
        TypeDefinitionMaster master = typeDefinitionMasterService.getById(typeDefinition.getMasterId());
        if(master == null){
            return null;
        }else {
            return StringUtils.isEmpty(master.getReferenceTable())?null:(master.getReferenceTable() + REFERENCE_TABLE_POSTFIX);
        }
    }


    private Map<Long, List<AttributeDetailView>> assembleAttributeDetailViewsByTyped(List<LocalAttributeModel> localAttributeModels, List<? extends Typed> typedList) {
        Map<Long, Map<Long, List<AbstractValueView>>> attributeValueViewMap = getAllAttributeValues(localAttributeModels, typedList);
        Map<Long, List<AttributeDetailView>> mapAttributeDetailView = new HashMap<>();
        typedList.forEach(typed -> {
            List<AttributeDetailView> list = localAttributeModels.stream().map(localAttributeModel -> {
                AttributeDetailView attributeDetailView = null;
                // 判断是否存在当前类型
                // 判断是否包含值。
                if (attributeValueViewMap.containsKey(typed.getId()) &&
                        attributeValueViewMap.get(typed.getId()).containsKey(localAttributeModel.getGlobalAttributeId())) {
                    Map<Long, List<AbstractValueView>> attributeIDValueViewMap = attributeValueViewMap.get(typed.getId());
                    List<AbstractValueView> AbstractValueViewList = attributeIDValueViewMap.get(localAttributeModel.getGlobalAttributeId());
                    if (!CollectionUtils.isEmpty(AbstractValueViewList)) {
                        attributeDetailView = new AttributeDetailView(localAttributeModel, AbstractValueViewList);
                    }
                } else if (existInDataType(localAttributeModel.getDataTypeName())) {
                    attributeDetailView = new AttributeDetailView(localAttributeModel, null);
                }
                return attributeDetailView;
            }).filter(Objects::nonNull).collect(Collectors.toList());
            mapAttributeDetailView.put(typed.getId(), list);
        });

        return mapAttributeDetailView;
    }

    public boolean existInDataType(String dataName){
        return Arrays.stream(DataTypeEnum.values()).map(DataTypeEnum::getType).collect(Collectors.toSet()).contains(dataName);
    }
    protected Map<Long, Map<Long, List<AbstractValueView>>> getAllAttributeValues(List<LocalAttributeModel> localAttributeModels, List<? extends Typed> typedList) {
        Map<? extends Typed, List<AbstractValueView>> valueViewMap = queryValues(typedList,
                getTypeDetail(typedList.get(0).getTypeId()),localAttributeModels);
        return valueViewMap.entrySet().stream()
                .collect(Collectors.toMap(
                        entry -> entry.getKey().getId(),
                        entry -> entry.getValue().stream().collect(Collectors.groupingBy(AbstractValueView::getAttributeId, Collectors.toList())))
                );
    }

    public <T extends Typed> Map<T, List<AbstractValueView>> queryValues(List<T> typedList, TypeDefinitionModel typeDefinitionModel,
                                                                         List<LocalAttributeModel> localAttributeModels) {
        Map<T, List<AbstractValueView>> attributeValueViewMap = new HashMap<>();
        if(CollectionUtils.isEmpty(typedList)){
            return attributeValueViewMap;
        }
        try {
            Map<String, LocalAttributeModel> internalIdMap = localAttributeModels.stream()
                    .collect(Collectors.toMap(LocalAttributeModel::getInternalId, localAttributeModel -> localAttributeModel));
            queryValues(typedList, typeDefinitionModel, internalIdMap, attributeValueViewMap);
        } catch (SQLException e) {
            logger.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
        return attributeValueViewMap;
    }

    public <T extends Typed> void queryValues(List<T> typedList, TypeDefinitionModel typeDefinitionModel,
                                              Map<String, LocalAttributeModel> internalIdMap,
                                              Map<T, List<AbstractValueView>> attributeValueViewMap) throws SQLException {
        Map<Long, T> objectIdMap = typedList.stream().collect(Collectors.toMap(Typed::getId, typed -> typed, (v1, v2) -> v1));
        //查询类型属性表名
        String tableName = getAttributeTableFromTypeId(typeDefinitionModel.getId());
        String ids = "";
        for(Long id: objectIdMap.keySet()){
            ids += id + ",";
        }
        String sql = "select * from " + tableName + " where id in(" + ids.substring(0, ids.length()-1) + ")";
        logger.debug("queryValues>sql:{}", sql);

            List<Map<String, Object>> result = SqlRunner.db().selectList(sql);
            for(int i=0; i<result.size(); i++){
                Map<String, Object> map = result.get(i);
                long id = (Long)map.get(REFERENCE_TABLE_ID);
                T t = objectIdMap.get(id);
                List<AbstractValueView> valueViews = new ArrayList<>();

                for (String columnName: map.keySet()) {
                    if (internalIdMap.containsKey(columnName)) {
                        LocalAttributeModel localAttributeModel = internalIdMap.get(columnName);
                        String dataType = localAttributeModel.getDataTypeName();
                        Object value = map.get(columnName);
                        /*
                         * if it's data type is String, and it's a multiple value attribute then split the value with
                         * indicate splitter
                         */
                        if (value != null) {
                            if (localAttributeModel.getDataTypeName().equals(DataTypeEnum.NAME_STRING.name()) && localAttributeModel.isMultipleValue()) {
                                String[] multipleValues = value.toString().split(MULTIPLE_VALUE_SPLITTER);
                                for (String splitValue : multipleValues) {
                                    AbstractValueView abstractValueView = new StringValueView(localAttributeModel.getGlobalAttributeId(), splitValue);
                                    valueViews.add(abstractValueView);
                                }
                            } else {
                                AbstractValueView abstractValueView = new StringValueView(localAttributeModel.getGlobalAttributeId(), value.toString());
                                valueViews.add(abstractValueView);
                            }
                        }
                    }
                }
                attributeValueViewMap.put(t, valueViews);
            }

    }

    private void transformTypeDefinition(TypeDefinitionDTO typeDefinitionDTO, TypeDefinitionModel typeDefinitionModel) {
        if (typeDefinitionDTO != null) {
            BeanUtils.copyProperties(typeDefinitionDTO, typeDefinitionModel);
            // 修改localattributeDTOList 为 localAttributeModelGroup
            if (!CollectionUtils.isEmpty(typeDefinitionDTO.getAttributeGroups())) {
                LinkedHashMap<String, List<LocalAttributeModel>> mapGroup = new LinkedHashMap<>();
                Map<String, String> attributeDataTypeMap = new HashMap<>();
                Map<String, String> attributeFormatMap = new HashMap<>();

                List<AttributeGroupModel> attributeGroupModels = new ArrayList<>();
                typeDefinitionDTO.getAttributeGroups().forEach(attributeGroupDTO -> {
                    if (!CollectionUtils.isEmpty(attributeGroupDTO.getLocalAttributes())) {
                        AttributeGroupModel attributeGroupModel = new AttributeGroupModel();
                        BeanUtils.copyProperties(attributeGroupDTO, attributeGroupModel);

                        attributeGroupModel.setLocalAttributeModels(attributeGroupDTO.getLocalAttributes().stream().map(localAttributeDTO -> {
                            LocalAttributeModel localAttributeModel = new LocalAttributeModel();
                            BeanUtils.copyProperties(localAttributeDTO, localAttributeModel);
                            localAttributeModel.setAttributeType(localAttributeDTO.getLocalAttrType());
                            localAttributeModel.setGroupName(attributeGroupDTO.getName());
//                            if (!CollectionUtils.isEmpty(localAttributeDTO.getConstraints())) {
//                                localAttributeModel.setConstraintModelList(localAttributeDTO.getConstraints().stream().map(localConstant -> {
//                                    ConstraintModel constraintModel = new ConstraintModel();
//                                    BeanUtils.copyProperties(localConstant, constraintModel);
//                                    return constraintModel;
//                                }).collect(Collectors.toList()));
//                            }
                            attributeDataTypeMap.put(localAttributeModel.getName(), localAttributeModel.getDataTypeName());
                            attributeFormatMap.put(localAttributeModel.getName(), localAttributeModel.getFormat());
                            return localAttributeModel;
                        }).collect(Collectors.toList()));
                        attributeGroupModels.add(attributeGroupModel);
                    }
                });
                if (!CollectionUtils.isEmpty(attributeGroupModels)) {
                    typeDefinitionModel.setAttributeGroupModels(attributeGroupModels.stream().map(attributeGroupModel -> {
                                if (attributeGroupModel != null && attributeGroupModel.getLocalAttributeModels() != null) {
                                    attributeGroupModel.setLocalAttributeModels(
                                            attributeGroupModel.getLocalAttributeModels().stream().map(localAttributeModel -> {
                                                //if data type is reference then get referenced attribute data type
//                                                if (localAttributeModel.getDataTypeName().equalsIgnoreCase(DataTypeConstant.DATATYPE_REFERENCE)) {
//                                                    //this attribute should not be null as it will be validated when attribute maintained
//                                                    String referenceAttribute = localAttributeModel.getReferencedAttribute();
//                                                    if(referenceAttribute != null){
//                                                        String[] splitStr = referenceAttribute.split("\\.");  // index 0 is type name, index 1 is attribute name
//                                                        if (splitStr.length == 2) {
//                                                            //if reference self value
//                                                            if (splitStr[0].equals(typeDefinitionModel.getInternalName())) {
//                                                                localAttributeModel.setReferencedDataType(attributeDataTypeMap.get(splitStr[1]));
//                                                                localAttributeModel.setFormat(attributeFormatMap.get(splitStr[1]));
//                                                            } else {
//                                                                LocalAttributeModel referencedAttributeDataModel = getLocalAttribute(splitStr[0], splitStr[1]);
//                                                                if (referencedAttributeDataModel != null) {
//                                                                    localAttributeModel.setReferencedDataType(referencedAttributeDataModel.getDataTypeName());
//                                                                    localAttributeModel.setFormat(referencedAttributeDataModel.getFormat());
//                                                                }
//                                                            }
//                                                        }
//                                                    }
//                                                }
                                                return localAttributeModel;
                                            }).collect(Collectors.toList()));
                                }
                                return attributeGroupModel;
                            }).collect(Collectors.toList())
                    );
                }

                typeDefinitionModel.setLocalAttributes(Collections.emptyList());
                if(!CollectionUtils.isEmpty(typeDefinitionModel.getAttributeGroupModels())) {
                    List<LocalAttributeModel> localAttributes = new ArrayList<>();
                    typeDefinitionModel.getAttributeGroupModels().forEach(attributeGroupModel -> {
                        List<LocalAttributeModel> localAttributeModels1 = attributeGroupModel.getLocalAttributeModels();
                        if(!CollectionUtils.isEmpty(localAttributeModels1)){
                            localAttributeModels1 = localAttributeModels1.stream().filter(Objects::nonNull).collect(Collectors.toList());
                            localAttributes.addAll(localAttributeModels1);
                        }
                    });
                    typeDefinitionModel.setLocalAttributes(localAttributes);
                }

                typeDefinitionModel.setLocalAttributesWithGroup(new LinkedHashMap<>());
                if (!CollectionUtils.isEmpty(typeDefinitionModel.getAttributeGroupModels())) {
                    LinkedHashMap<String, List<LocalAttributeModel>> localAttributesWithGroup = new LinkedHashMap<>();
                    typeDefinitionModel.getAttributeGroupModels().forEach(attributeGroupModel -> {
                        List<LocalAttributeModel> localAttributeModels1 = attributeGroupModel.getLocalAttributeModels();
                        if (!CollectionUtils.isEmpty(localAttributeModels1)) {
                            localAttributeModels1 = localAttributeModels1.stream().filter(Objects::nonNull).collect(Collectors.toList());
                            localAttributesWithGroup.put(attributeGroupModel.getName(), localAttributeModels1);
                        }
                    });
                    typeDefinitionModel.setLocalAttributesWithGroup(localAttributesWithGroup);
                }
            }
        }
    }

//    public Object toTypeConversion(AbstractValueView attributeValueView, List<AttributeDetailView>  attributeDetailViews) throws ParseException {
//        Optional<AttributeDetailView> optional = attributeDetailViews.stream()
//                .filter(p -> p.getLocalAttributeModel().getGlobalAttributeId().equals(attributeValueView.getAttributeId())).findFirst();
//        if (optional.isPresent() && DATA_TIME_TYPE_NAME.equals(optional.get().getLocalAttributeModel().getDataTypeName())) {
//            String attributeValue = attributeValueView.getValue().replaceAll("/", "-");
//            try {
//                return new Timestamp(new SimpleDateFormat(DATA_TIME_FORMAT).parse(attributeValue).getTime());
//            } catch (Exception ex) {
//                throw new ServiceException("The format of the date field is incorrect,value:" + attributeValue , CommonMsgEnum.FAIL.getCode());
//            }
//        }
//        return attributeValueView.getValue();
//    }

    @Override
    public TypeDefinitionTreeModel getTypeMultipleLevelTree(long typeId){
        TypeDefinitionTreeDTO typeDefinitionTreeDTO = typeDefinitionService.findTypeMultipleLevelTree(typeId);
        if (typeDefinitionTreeDTO != null) {
            TypeDefinitionTreeModel typeDefinitionTreeModel = new TypeDefinitionTreeModel();
            transformTypeDefinitionTree(typeDefinitionTreeDTO, typeDefinitionTreeModel);
            return typeDefinitionTreeModel;
        }
        return null;
    }


    @Override
    public TypeDefinitionTreeModel getTypeMultipleLevelTree(String typeInternalName){
        TypeDefinitionTreeDTO typeDefinitionTreeDTO = typeDefinitionService.findTypeMultipleLevelTree(typeInternalName);
        if (typeDefinitionTreeDTO != null) {
            TypeDefinitionTreeModel typeDefinitionTreeModel = new TypeDefinitionTreeModel();
            transformTypeDefinitionTree(typeDefinitionTreeDTO, typeDefinitionTreeModel);
            return typeDefinitionTreeModel;
        }
        return null;
    }

    private void transformTypeDefinitionTree(TypeDefinitionTreeDTO typeDefinitionTreeDTO, TypeDefinitionTreeModel typeDefinitionTreeModel) {
        if (typeDefinitionTreeDTO != null) {
            BeanUtils.copyProperties(typeDefinitionTreeDTO, typeDefinitionTreeModel);
            // 修改localattributeDTOList 为 localAttributeModelGroup
            if (!CollectionUtils.isEmpty(typeDefinitionTreeDTO.getSubTypes())) {
                typeDefinitionTreeModel.setSubTypes(typeDefinitionTreeDTO.getSubTypes().stream().map(typeDTO -> {
                    TypeDefinitionTreeModel typeModel = new TypeDefinitionTreeModel();
                    transformTypeDefinitionTree(typeDTO, typeModel);
                    return typeModel;
                }).collect(Collectors.toList()));
            } else {
                typeDefinitionTreeModel.setSubTypes(new ArrayList<>());
            }
        }
    }

    @Override
    public TypeDefinitionModel getTypeDetail(Long typeId) {
        if (typeId == null) {
            return null;
        }
        TypeDefinitionDTO typeDefinitionDTO = typeDefinitionService.queryDetail(typeId);
        if (typeDefinitionDTO != null) {
            TypeDefinitionModel typeDefinitionModel = new TypeDefinitionModel();
            transformTypeDefinition(typeDefinitionDTO, typeDefinitionModel);
            return typeDefinitionModel;
        }
        return null;
    }

    @Override
    public TypeDefinitionModel getTypeDetail(String typeInternalName) {
        if (typeInternalName == null) {
            return null;
        }
        TypeDefinitionDTO typeDefinitionDTO = typeDefinitionService.queryDetail(typeInternalName);
        if (typeDefinitionDTO != null) {
            TypeDefinitionModel typeDefinitionModel = new TypeDefinitionModel();
            transformTypeDefinition(typeDefinitionDTO, typeDefinitionModel);
            return typeDefinitionModel;
        }
        return null;
    }

    @Override
    public List<LocalAttributeModel> getLocalAttributeModels(Long typeId) {
        TypeDefinitionModel typeDefinitionModel = this.getTypeDetail(typeId);
        return typeDefinitionModel != null ? typeDefinitionModel.getLocalAttributes() : null;
    }

    private List<LocalAttributeModel> getLocalAttributeModels(Typed typed, List<Long> attributeIds) {
        List<LocalAttributeModel> localAttributeModels = getLocalAttributeModels(typed.getTypeId());
        if (CollectionUtils.isEmpty(localAttributeModels)) {
            return new ArrayList<>();
        }

        return localAttributeModels.stream()
                .filter(localAttributeModel -> attributeIds.contains(localAttributeModel.getGlobalAttributeId()))
                .collect(Collectors.toList());
    }

    @Override
    public AttributeDetailView getAttributeValue(Typed typed, String attributeName){
        if(attributeName == null){
            return null;
        }
        List<AttributeDetailView> list = getAttributeValues(typed).stream().filter(attributeDetailView -> {
            if (attributeDetailView == null || attributeDetailView.getLocalAttributeModel() == null) {
                return false;
            }
            return attributeName.equals(attributeDetailView.getLocalAttributeModel().getName());
        }).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(list)) {
            return list.get(0);
        }
        return null;
    }
}
